package com.tebiecloud.mpweixin.server.controller;

import com.alibaba.fastjson.JSONObject;
import com.tebiecloud.common.constants.ResultEnum;
import com.tebiecloud.common.model.ResultBody;
import com.tebiecloud.common.utils.JsonUtils;
import com.tebiecloud.common.utils.RandomValueUtils;
import com.tebiecloud.common.utils.RedisUtils;
import com.tebiecloud.common.utils.ResultBodyUtils;
import com.tebiecloud.mpweixin.client.constants.MpweixinConstants;
import com.tebiecloud.mpweixin.client.model.entity.MpweixinMggFlow;
import com.tebiecloud.mpweixin.server.properties.MpweixinProperties;
import com.tebiecloud.mpweixin.server.service.feign.MpopenApiServiceClient;
import com.tebiecloud.mpweixin.server.utils.MPApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * 微信公众号接口
 * @Author: tebie
 * @Date: 2019-10-07 16:04
 */
@Slf4j
@RestController
@RequestMapping("/mpweixinapi")
public class MpweixinApiController {

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private MpweixinProperties mpweixinProperties;

    @Autowired
    private MpopenApiServiceClient mpopenApiServiceClient;

    /**
     * 获取公众号jssdk配置信息
     * @param url
     * @return
     */
    @PostMapping("infoJssdkConf")
    public ResultBody infoJssdkConf(@RequestParam("url") String url) {
        // 微信参数信息
        if(!StringUtils.isEmpty(url)) {
            String appId = mpweixinProperties.getAppid(); // 必填，公众号的唯一标识
            String ticket = getTicket(appId);
            if(ticket != null) {
                String timestamp = String.valueOf(System.currentTimeMillis() / 1000); // 必填，生成签名的时间戳
                String nonceStr = RandomValueUtils.randomStr(16, true, true, true); // 必填，生成签名的随机串

                String sign = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr + "&timestamp=" + timestamp + "&url=" + url;
                String signature = DigestUtils.sha1Hex(sign);// 必填，签名，见附录1

                Map<String, Object> wxconfig = new HashMap<String, Object>();
                wxconfig.put("appId", appId);
                wxconfig.put("timestamp", timestamp);
                wxconfig.put("nonceStr", nonceStr);
                wxconfig.put("signature", signature);

                log.info("xiaoc>> 获取公众号jssdk配置信息，appId: {}, timestamp: {}, nonceStr: {}, signature: {}, sign: {}", appId, timestamp, nonceStr, signature, sign);

                return ResultBodyUtils.ok(wxconfig);
            } else {
                log.info("xiaoc>> 获取公众号jssdk配置信息失败，获取ticket失败");
            }
        } else {
            log.info("xiaoc>> 获取公众号jssdk配置信息，url 为空");
        }

        return ResultBodyUtils.failed("获取jssdk配置信息失败");
    }

    /**
     * 获取公众号jsapi_ticket
     * @param appid
     * @return
     */
    public String getTicket(String appid) {
        String ticket = redisUtils.get(MpweixinConstants.REDIS_MP_JSAPI_TICKET_ + appid);
        if (StringUtils.isEmpty(ticket)) {
            // 获取全局锁
            int tryTimes = 0; // 尝试次数
            while (tryTimes++ < 3) {
                if(redisUtils.lock(MpweixinConstants.REDIS_MP_JSAPI_TICKET_, 5)) {
                    ticket = redisUtils.get(MpweixinConstants.REDIS_MP_JSAPI_TICKET_ + appid);
                    if (StringUtils.isEmpty(ticket)) {
                        ResultBody<String> respAccessToekn = mpopenApiServiceClient.getWxapiAccessToken(appid, false);
                        if(respAccessToekn.getCode() != ResultEnum.OK.getCode()) {
                            log.info("获取公众号jsapi_ticket失败, respAccessToekn: {}", JsonUtils.Obj2Str(respAccessToekn));
                            return null;
                        }

                        String resp = MPApi.getticket(respAccessToekn.getData());
                        JSONObject jsonResp = JsonUtils.str2Json(resp);
                        if (jsonResp != null && !StringUtils.isEmpty(jsonResp.getString("ticket"))) {
                            ticket = jsonResp.getString("ticket");

                            int seconds = 7000; // 默认存活7000秒
                            if (jsonResp.getIntValue("expires_in") > 200) {
                                seconds = jsonResp.getIntValue("expires_in") - 200;
                            }
                            redisUtils.set(MpweixinConstants.REDIS_MP_JSAPI_TICKET_ + appid, ticket, seconds);

                            redisUtils.unLock(MpweixinConstants.REDIS_MP_JSAPI_TICKET_);
                            break;
                        }
                    } else {
                        redisUtils.unLock(MpweixinConstants.REDIS_MP_JSAPI_TICKET_);
                        break;
                    }
                } else {
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        return ticket;
    }

}
